#include <iostream>
#include <functional>

#include "contact_server.hpp"

using namespace web_contacts;

int main()
{
    httplib::Server server;
    cout << "--->服务器启动" << endl;
    ContactServer contact_server;
    //绑定url处理方法
    //添加联系人
    server.Post("/contact/add", [contact_server](const httplib::Request &req, httplib::Response &resp){
        AddContactRequest request;
        AddContactResponce responce;
        //反序列化请求
        try{
            if(!request.ParseFromString(req.body))
                throw ContactException("parse request error!\n");
            //添加联系人
            contact_server.addContact(request, &responce); 
            //将responce序列化
            std::string resp_str;
            if(!responce.SerializePartialToString(&resp_str))
                throw ContactException("serialize responce error!\n");
            //到此正常返回响应
            resp.body = resp_str;
            resp.status = 200;
            resp.set_header("Content-Type", "application/protobuf");
        }
        catch(ContactException& e)
        {
            //不能简单打印错误信息，还要返回响应给客户端
            std::cerr << "---> /contact/add 异常, 错误信息: " << e.what();
            resp.status = 500;
            base_resp::BaseResponce *baseResponce = responce.mutable_base_resp();
            baseResponce->set_success(false);
            baseResponce->set_desc_str(e.what());
            //序列化
            std::string responce_str;
            if(responce.SerializeToString(&responce_str)){
                resp.body = responce_str;
                resp.set_header("Content-Type", "application/protobuf");
            }
        }
    });

    //查询联系人
    server.Post("/contact/find-one", [contact_server](const httplib::Request &req, httplib::Response &resp){
        find_one_req::FindOneRequest request;
        find_one_res::FindOneRespone responce;
        //反序列化请求
        try
        {
            if(!request.ParseFromString(req.body))
                throw ContactException("parse request error!\n");
            //调用底层
            contact_server.findOne(request, &responce);
            std::string resp_str;
            if(!responce.SerializeToString(&resp_str))
                throw ContactException("Serialize responce error!\n");
            //到此可以正常返回
            resp.status = 200;
            resp.body = resp_str;
            resp.set_header("Content-Type", "application/protobuf");
        }
        catch(ContactException &e)
        {
            std::cerr << "---> /contact/find-one 异常, 错误信息: " << e.what();
            resp.status = 500;
            //protobuf中的错误信息
            base_resp::BaseResponce *baseResponce = responce.mutable_base_resp();
            baseResponce->set_success(false);
            baseResponce->set_desc_str(e.what());
            //序列化
            std::string responce_str;
            if(responce.SerializeToString(&responce_str)){
                resp.body = responce_str;
                resp.set_header("Content-Type", "application/protobuf");
            }
        }
    });

    //删除指定联系人
    server.Post("/contact/del", [contact_server](const httplib::Request &req, httplib::Response &resp){
        del_contact_req::DelContactRequest request;
        del_contact_resp::DelContactResponce responce;
        try
        {
            //从请求体中取出数据反序列化
            if(!request.ParseFromString(req.body))
                throw ContactException("/contact/del request parse error!\n");
            contact_server.delContact(request, &responce);
            //构造响应返回
            std::string resp_str;
            if(!responce.SerializeToString(&resp_str))
                throw ContactException("/contact/del responce serizlize error!\n");
            resp.status = 200;
            resp.body = resp_str;
            resp.set_header("Content-Type", "application/protobuf");
        }
        catch(const ContactException& e)
        {
            //服务端打印错误信息
            std::cerr << "---> post '/contact/del' 请求失败, 错误原因: " << e.what();
            //构造响应，反应错误给客户端
            base_resp::BaseResponce *base_resp = responce.mutable_base_resp();
            base_resp->set_success(false);
            base_resp->set_desc_str(e.what());
            //序列化响应
            std::string resp_str;
            resp.status = 500;
            if(responce.SerializeToString(&resp_str))
                resp.body = resp_str;//序列化成功才构造响应
        }
    });

    //查找所有联系人
    server.Get("/contact/find-all", [contact_server](const httplib::Request &req, httplib::Response &resp){
        find_all_resp::FindAllResponce responce;
        try
        {
            //调用server的查找联系人的方法
            contact_server.findAll(&responce);
            //序列化
            std::string resp_str;
            if(!responce.SerializeToString(&resp_str))
                throw ContactException("/contact/find-all responce序列化失败!\n");
            resp.body = resp_str;
            resp.status = 200;
            resp.set_header("Content-Type", "application/protobuf");
        }
        catch(const ContactException &e)
        {
            std::cerr << "/contact/find-all 服务失败, 错误原因: " << e.what();
            auto base_resp = responce.mutable_base_resp();
            base_resp->set_success(false);
            base_resp->set_desc_str(e.what());
            //序列化
            std::string resp_str;
            resp.status = 500;
            if(responce.SerializeToString(&resp_str))
                resp.body = resp_str;
        }
    });

    server.listen("0.0.0.0", 8888);
}